{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's start by opening the file and analyzing native references:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------- PARSING VM SNAPSHOT --------\n",
      "\n",
      "[Header]\n",
      "  length = 4733\n",
      "  kind = 2 ('kFullAOT', 'Full + AOT code')\n",
      "\n",
      "[Snapshot header]\n",
      "  version = 'c8562f0ee0ebc38ba217c7955956d1cb'\n",
      "  features = {'product': True, 'use_bare_instructions': True, 'asserts\"': False, 'causal_async_stacks': True, 'bytecode': False, 'arm-eabi': True, 'softfp': True}\n",
      "\n",
      "  base objects: 95\n",
      "  objects: 935\n",
      "  clusters: 5\n",
      "  code order length = 69\n",
      "\n",
      "[002c1094]: INFO: Reading allocation clusters...\n",
      "[002c13a9]: INFO: Reading fill clusters...\n",
      "[002c2215]: INFO: Reading roots...\n",
      "[002c2281]: INFO: Snapshot parsed.\n",
      "\n",
      "------- PARSING ISOLATE SNAPSHOT --------\n",
      "\n",
      "[Header]\n",
      "  length = 836159\n",
      "  kind = 2 ('kFullAOT', 'Full + AOT code')\n",
      "\n",
      "[Snapshot header]\n",
      "  version = 'c8562f0ee0ebc38ba217c7955956d1cb'\n",
      "  features = {'product': True, 'use_bare_instructions': True, 'asserts\"': False, 'causal_async_stacks': True, 'bytecode': False, 'arm-eabi': True, 'softfp': True}\n",
      "\n",
      "  base objects: 935\n",
      "  objects: 74247\n",
      "  clusters: 222\n",
      "  code order length = 7228\n",
      "\n",
      "[002c7098]: INFO: Reading allocation clusters...\n",
      "[002d8228]: INFO: Reading fill clusters...\n",
      "[00393161]: INFO: Reading roots...\n",
      "[00393243]: INFO: Snapshot parsed.\n",
      "Starting analysis...\n",
      "Done in 3.12s, processing results\n"
     ]
    }
   ],
   "source": [
    "from darter.file import parse_elf_snapshot, parse_appjit_snapshot\n",
    "from darter.asm.base import populate_native_references\n",
    "\n",
    "s = parse_elf_snapshot('samples/arm-app.so')\n",
    "populate_native_references(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will import the constants and define some basic functions to help us analyze the data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "import re\n",
    "from darter.constants import *\n",
    "from collections import defaultdict\n",
    "\n",
    "def is_irrelevant(src):\n",
    "    if src[0] == src[0].s.refs['root'].x['global_object_pool']: return True\n",
    "    if src[0] == src[0].s.refs['root'].x['symbol_table']: return True\n",
    "\n",
    "def show_rev_tree(ref, depth=4, max_srcs=5, i_step=4, hide_irrelevant=True, hide_location=True):\n",
    "    ''' Shows a tree of back-references to an object; that is, things pointing to it. '''\n",
    "    def show_src(src, depth, roots=set(), indent=0):\n",
    "        x, *rest = src\n",
    "        location = x.locate()\n",
    "        location_str = ' {{ {} }}'.format(' '.join(map(str, location))) if location else ''\n",
    "        print(' '*indent + '{} ({})'.format(x, ' '.join(map(str, rest))) + location_str)\n",
    "        if depth > 0:\n",
    "            roots, indent = roots | {x}, indent + i_step\n",
    "            if hide_location and location: roots |= set(location)\n",
    "            srcs = x.src + getattr(x, 'nsrc', [])\n",
    "            filter_out = lambda src: (src[0] in roots) or (hide_irrelevant and is_irrelevant(src))\n",
    "            srcs = [ src for src in srcs if not filter_out(src) ]\n",
    "            for csrc in srcs[:max_srcs]: show_src(csrc, depth-1, roots, indent)\n",
    "            if len(srcs) > max_srcs: print(\" \"*(indent) + '... {} more'.format(len(srcs)-max_srcs))\n",
    "    show_src((ref,), depth)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Export R2 metadata\n",
    "\n",
    "This exports part of the parsed data into metadata for loading into [Radare2](https://www.radare.org/r/), which can be useful for manual close analysis of the assembled code, or for Darter development.\n",
    "\n",
    "Flags are created for every code section (describing the code object), so you can seek / disassemble them more easily.  \n",
    "Comments are placed at every native reference, describing the loaded object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import defaultdict\n",
    "from base64 import b64encode\n",
    "do_b64 = lambda x: 'base64:' + b64encode(x.encode('utf-8')).decode('ascii')\n",
    "\n",
    "def produce_metadata(snapshot):\n",
    "    out = []\n",
    "    comments = defaultdict(lambda: [])\n",
    "    out.append('fs functions')\n",
    "    for code in snapshot.getrefs('Code'):\n",
    "        instr = code.x['instructions']\n",
    "        name = 'c_{}'.format(code.ref)\n",
    "        comment = ' '.join(map(str, code.locate()))\n",
    "        out.append('f {name} {len} {addr} {c}'.format( name=name, len=len(instr['data']), addr=instr['data_addr'], c=do_b64(comment) ))\n",
    "        for target, pc, kind, *args in code.x.get('nrefs', []):\n",
    "            if kind == 'load':\n",
    "                comments[pc].append( 'load: {reg} = {tg}'.format(tg=target.describe(), reg=args[0]) )\n",
    "    for addr, lines in comments.items():\n",
    "        out.append('CCu {} @ {}'.format( do_b64(\"\\n\".join(lines)), addr ))\n",
    "    return ''.join(x + '\\n' for x in out)\n",
    "\n",
    "with open('metadata.r2', 'w') as f: f.write(produce_metadata(s))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To load the metadata, open the file in Radare2 and do: `. metadata.r2`  \n",
    "Then, seek to a certain code object (`s c_18052`) and dissassemble it (`pD $(fl)`).  \n",
    "The color of the annotations can be changed through something like: `ec comment rgb:f0f000`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Print string table\n",
    "\n",
    "In order to do an initial reconnaissance, we can dump all strings in the application.  \n",
    "The following code does that, excluding strings that look like obfuscated identifiers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "ID_PATTERN = r'(([sg]et|init|dyn)\\:)?_?[a-zA-Z]{1,3}(\\@\\d+)?.?'   # pattern to ignore\n",
    "REF_ORDER = True    # False sorts strings alphabetically\n",
    "\n",
    "with open('app-strings.txt', 'w') as f:\n",
    "    key = (lambda x: x.ref) if REF_ORDER else (lambda x: x.x['value'])\n",
    "    for x in sorted(s.strings_refs, key=key):\n",
    "        if re.fullmatch(ID_PATTERN, x.x['value']): continue\n",
    "        print('{} {}'.format(x.ref, repr(x.x['value'])), file=f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Find relevant libraries\n",
    "\n",
    "Most of the application code, objects, strings, etc. will often be open-source dependencies rather than useful code.  \n",
    "Dart code is separated in *libraries*, so making a list of libraries that contain useful code is a big help."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Library('dart:_http')->11838\n",
      "Library('dart:_internal')->11853\n",
      "Library('dart:_vmservice')->11845\n",
      "Library('dart:async')->11859\n",
      "Library('dart:collection')->11857\n",
      "Library('dart:convert')->11856\n",
      "Library('dart:core')->11858\n",
      "Library('dart:developer')->11855\n",
      "Library('dart:ffi')->11854\n",
      "Library('dart:io')->11708\n",
      "Library('dart:isolate')->11852\n",
      "Library('dart:math')->11851\n",
      "Library('dart:mirrors')->11850\n",
      "Library('dart:nativewrappers')->11849\n",
      "Library('dart:profiler')->11848\n",
      "Library('dart:typed_data')->11846\n",
      "Library('dart:ui')->11626\n",
      "Library('dart:vmservice_io')->11843\n",
      "Library('package:collection/src/priority_queue.dart')->11830\n",
      "Library('package:flutter/src/animation/animation.dart')->11638\n",
      "Library('package:flutter/src/animation/animation_controller.dart')->11744\n",
      "Library('package:flutter/src/animation/animations.dart')->11642\n",
      "Library('package:flutter/src/animation/curves.dart')->11625\n",
      "Library('package:flutter/src/animation/listener_helpers.dart')->11643\n",
      "Library('package:flutter/src/animation/tween.dart')->11641\n",
      "Library('package:flutter/src/cupertino/action_sheet.dart')->11710\n",
      "Library('package:flutter/src/cupertino/localizations.dart')->11689\n",
      "Library('package:flutter/src/cupertino/route.dart')->11640\n",
      "Library('package:flutter/src/cupertino/text_theme.dart')->11751\n",
      "Library('package:flutter/src/cupertino/theme.dart')->11711\n",
      "Library('package:flutter/src/foundation/_isolates_io.dart')->11823\n",
      "Library('package:flutter/src/foundation/_platform_io.dart')->11836\n",
      "Library('package:flutter/src/foundation/assertions.dart')->11820\n",
      "Library('package:flutter/src/foundation/binding.dart')->11661\n",
      "Library('package:flutter/src/foundation/change_notifier.dart')->11637\n",
      "Library('package:flutter/src/foundation/collections.dart')->11834\n",
      "Library('package:flutter/src/foundation/debug.dart')->11815\n",
      "Library('package:flutter/src/foundation/diagnostics.dart')->11627\n",
      "Library('package:flutter/src/foundation/isolates.dart')->11822\n",
      "Library('package:flutter/src/foundation/key.dart')->11646\n",
      "Library('package:flutter/src/foundation/licenses.dart')->11824\n",
      "Library('package:flutter/src/foundation/node.dart')->11659\n",
      "Library('package:flutter/src/foundation/observer_list.dart')->11827\n",
      "Library('package:flutter/src/foundation/platform.dart')->11765\n",
      "Library('package:flutter/src/foundation/print.dart')->11821\n",
      "Library('package:flutter/src/foundation/serialization.dart')->11811\n",
      "Library('package:flutter/src/foundation/synchronous_future.dart')->11738\n",
      "Library('package:flutter/src/gestures/arena.dart')->11712\n",
      "Library('package:flutter/src/gestures/binding.dart')->11662\n",
      "Library('package:flutter/src/gestures/converter.dart')->11818\n",
      "Library('package:flutter/src/gestures/drag_details.dart')->11657\n",
      "Library('package:flutter/src/gestures/events.dart')->11814\n",
      "Library('package:flutter/src/gestures/force_press.dart')->11833\n",
      "Library('package:flutter/src/gestures/hit_test.dart')->11632\n",
      "Library('package:flutter/src/gestures/long_press.dart')->11715\n",
      "Library('package:flutter/src/gestures/lsq_solver.dart')->11714\n",
      "Library('package:flutter/src/gestures/monodrag.dart')->11652\n",
      "Library('package:flutter/src/gestures/mouse_tracking.dart')->11739\n",
      "Library('package:flutter/src/gestures/multitap.dart')->11653\n",
      "Library('package:flutter/src/gestures/pointer_router.dart')->11828\n",
      "Library('package:flutter/src/gestures/pointer_signal_resolver.dart')->11829\n",
      "Library('package:flutter/src/gestures/recognizer.dart')->11628\n",
      "Library('package:flutter/src/gestures/scale.dart')->11839\n",
      "Library('package:flutter/src/gestures/tap.dart')->11716\n",
      "Library('package:flutter/src/gestures/velocity_tracker.dart')->11713\n",
      "Library('package:flutter/src/material/app.dart')->11794\n",
      "Library('package:flutter/src/material/app_bar.dart')->11762\n",
      "Library('package:flutter/src/material/app_bar_theme.dart')->11725\n",
      "Library('package:flutter/src/material/arc.dart')->11771\n",
      "Library('package:flutter/src/material/back_button.dart')->11745\n",
      "Library('package:flutter/src/material/banner_theme.dart')->11732\n",
      "Library('package:flutter/src/material/bottom_app_bar_theme.dart')->11726\n",
      "Library('package:flutter/src/material/bottom_sheet.dart')->11841\n",
      "Library('package:flutter/src/material/bottom_sheet_theme.dart')->11730\n",
      "Library('package:flutter/src/material/button.dart')->11718\n",
      "Library('package:flutter/src/material/button_theme.dart')->11800\n",
      "Library('package:flutter/src/material/card_theme.dart')->11724\n",
      "Library('package:flutter/src/material/chip_theme.dart')->11806\n",
      "Library('package:flutter/src/material/color_scheme.dart')->11803\n",
      "Library('package:flutter/src/material/colors.dart')->11807\n",
      "Library('package:flutter/src/material/dialog_theme.dart')->11727\n",
      "Library('package:flutter/src/material/divider_theme.dart')->11733\n",
      "Library('package:flutter/src/material/drawer.dart')->11788\n",
      "Library('package:flutter/src/material/feedback.dart')->11694\n",
      "Library('package:flutter/src/material/flexible_space_bar.dart')->11772\n",
      "Library('package:flutter/src/material/floating_action_button.dart')->11796\n",
      "Library('package:flutter/src/material/floating_action_button_location.dart')->11719\n",
      "Library('package:flutter/src/material/floating_action_button_theme.dart')->11728\n",
      "Library('package:flutter/src/material/icon_button.dart')->11770\n",
      "Library('package:flutter/src/material/ink_highlight.dart')->11691\n",
      "Library('package:flutter/src/material/ink_splash.dart')->11670\n",
      "Library('package:flutter/src/material/ink_well.dart')->11671\n",
      "Library('package:flutter/src/material/input_decorator.dart')->11801\n",
      "Library('package:flutter/src/material/list_tile.dart')->11837\n",
      "Library('package:flutter/src/material/material.dart')->11672\n",
      "Library('package:flutter/src/material/material_localizations.dart')->11695\n",
      "Library('package:flutter/src/material/material_state.dart')->11746\n",
      "Library('package:flutter/src/material/page.dart')->11792\n",
      "Library('package:flutter/src/material/page_transitions_theme.dart')->11674\n",
      "Library('package:flutter/src/material/popup_menu_theme.dart')->11731\n",
      "Library('package:flutter/src/material/scaffold.dart')->11749\n",
      "Library('package:flutter/src/material/slider_theme.dart')->11721\n",
      "Library('package:flutter/src/material/snack_bar.dart')->11787\n",
      "Library('package:flutter/src/material/snack_bar_theme.dart')->11729\n",
      "Library('package:flutter/src/material/tab_bar_theme.dart')->11722\n",
      "Library('package:flutter/src/material/tabs.dart')->11777\n",
      "Library('package:flutter/src/material/text_theme.dart')->11804\n",
      "Library('package:flutter/src/material/theme.dart')->11750\n",
      "Library('package:flutter/src/material/theme_data.dart')->11747\n",
      "Library('package:flutter/src/material/toggle_buttons_theme.dart')->11720\n",
      "Library('package:flutter/src/material/tooltip.dart')->11735\n",
      "Library('package:flutter/src/material/tooltip_theme.dart')->11723\n",
      "Library('package:flutter/src/material/typography.dart')->11795\n",
      "Library('package:flutter/src/painting/alignment.dart')->11754\n",
      "Library('package:flutter/src/painting/basic_types.dart')->11774\n",
      "Library('package:flutter/src/painting/binding.dart')->11665\n",
      "Library('package:flutter/src/painting/border_radius.dart')->11799\n",
      "Library('package:flutter/src/painting/borders.dart')->11699\n",
      "Library('package:flutter/src/painting/box_border.dart')->11677\n",
      "Library('package:flutter/src/painting/box_decoration.dart')->11676\n",
      "Library('package:flutter/src/painting/box_shadow.dart')->11696\n",
      "Library('package:flutter/src/painting/circle_border.dart')->11697\n",
      "Library('package:flutter/src/painting/clip.dart')->11680\n",
      "Library('package:flutter/src/painting/colors.dart')->11753\n",
      "Library('package:flutter/src/painting/decoration.dart')->11639\n",
      "Library('package:flutter/src/painting/decoration_image.dart')->11835\n",
      "Library('package:flutter/src/painting/edge_insets.dart')->11802\n",
      "Library('package:flutter/src/painting/geometry.dart')->11840\n",
      "Library('package:flutter/src/painting/gradient.dart')->11656\n",
      "Library('package:flutter/src/painting/image_cache.dart')->11825\n",
      "Library('package:flutter/src/painting/image_provider.dart')->11741\n",
      "Library('package:flutter/src/painting/inline_span.dart')->11758\n",
      "Library('package:flutter/src/painting/matrix_utils.dart')->11808\n",
      "Library('package:flutter/src/painting/placeholder_span.dart')->11775\n",
      "Library('package:flutter/src/painting/rounded_rectangle_border.dart')->11698\n",
      "Library('package:flutter/src/painting/shader_warm_up.dart')->11666\n",
      "Library('package:flutter/src/painting/stadium_border.dart')->11700\n",
      "Library('package:flutter/src/painting/strut_style.dart')->11842\n",
      "Library('package:flutter/src/painting/text_painter.dart')->11759\n",
      "Library('package:flutter/src/painting/text_span.dart')->11791\n",
      "Library('package:flutter/src/painting/text_style.dart')->11805\n",
      "Library('package:flutter/src/physics/simulation.dart')->11743\n",
      "Library('package:flutter/src/physics/spring_simulation.dart')->11701\n",
      "Library('package:flutter/src/physics/tolerance.dart')->11742\n",
      "Library('package:flutter/src/physics/utils.dart')->11832\n",
      "Library('package:flutter/src/rendering/binding.dart')->11668\n",
      "Library('package:flutter/src/rendering/box.dart')->11630\n",
      "Library('package:flutter/src/rendering/custom_layout.dart')->11736\n",
      "Library('package:flutter/src/rendering/custom_paint.dart')->11678\n",
      "Library('package:flutter/src/rendering/debug_overflow_indicator.dart')->11756\n",
      "Library('package:flutter/src/rendering/error.dart')->11817\n",
      "Library('package:flutter/src/rendering/flex.dart')->11755\n",
      "Library('package:flutter/src/rendering/layer.dart')->11636\n",
      "Library('package:flutter/src/rendering/object.dart')->11631\n",
      "Library('package:flutter/src/rendering/paragraph.dart')->11757\n",
      "Library('package:flutter/src/rendering/performance_overlay.dart')->11763\n",
      "Library('package:flutter/src/rendering/proxy_box.dart')->11633\n",
      "Library('package:flutter/src/rendering/shifted_box.dart')->11629\n",
      "Library('package:flutter/src/rendering/stack.dart')->11737\n",
      "Library('package:flutter/src/rendering/view.dart')->11826\n",
      "Library('package:flutter/src/rendering/viewport_offset.dart')->11783\n",
      "Library('package:flutter/src/scheduler/binding.dart')->11664\n",
      "Library('package:flutter/src/scheduler/ticker.dart')->11648\n",
      "Library('package:flutter/src/semantics/binding.dart')->11667\n",
      "Library('package:flutter/src/semantics/semantics.dart')->11760\n",
      "Library('package:flutter/src/semantics/semantics_event.dart')->11693\n",
      "Library('package:flutter/src/semantics/semantics_service.dart')->11752\n",
      "Library('package:flutter/src/services/asset_bundle.dart')->11635\n",
      "Library('package:flutter/src/services/binary_messenger.dart')->11816\n",
      "Library('package:flutter/src/services/binding.dart')->11663\n",
      "Library('package:flutter/src/services/haptic_feedback.dart')->11734\n",
      "Library('package:flutter/src/services/keyboard_key.dart')->11654\n",
      "Library('package:flutter/src/services/message_codec.dart')->11810\n",
      "Library('package:flutter/src/services/message_codecs.dart')->11809\n",
      "Library('package:flutter/src/services/platform_channel.dart')->11707\n",
      "Library('package:flutter/src/services/raw_keyboard.dart')->11655\n",
      "Library('package:flutter/src/services/raw_keyboard_android.dart')->11685\n",
      "Library('package:flutter/src/services/raw_keyboard_fuchsia.dart')->11684\n",
      "Library('package:flutter/src/services/raw_keyboard_linux.dart')->11682\n",
      "Library('package:flutter/src/services/raw_keyboard_macos.dart')->11683\n",
      "Library('package:flutter/src/services/system_chrome.dart')->11764\n",
      "Library('package:flutter/src/services/system_navigator.dart')->11819\n",
      "Library('package:flutter/src/services/system_sound.dart')->11692\n",
      "Library('package:flutter/src/services/text_editing.dart')->11761\n",
      "Library('package:flutter/src/widgets/annotated_region.dart')->11768\n",
      "Library('package:flutter/src/widgets/app.dart')->11789\n",
      "Library('package:flutter/src/widgets/automatic_keep_alive.dart')->11673\n",
      "Library('package:flutter/src/widgets/banner.dart')->11702\n",
      "Library('package:flutter/src/widgets/basic.dart')->11634\n",
      "Library('package:flutter/src/widgets/binding.dart')->11669\n",
      "Library('package:flutter/src/widgets/container.dart')->11748\n",
      "Library('package:flutter/src/widgets/focus_manager.dart')->11660\n",
      "Library('package:flutter/src/widgets/focus_scope.dart')->11706\n",
      "Library('package:flutter/src/widgets/focus_traversal.dart')->11776\n",
      "Library('package:flutter/src/widgets/framework.dart')->11645\n",
      "Library('package:flutter/src/widgets/gesture_detector.dart')->11703\n",
      "Library('package:flutter/src/widgets/grid_paper.dart')->11679\n",
      "Library('package:flutter/src/widgets/heroes.dart')->11778\n",
      "Library('package:flutter/src/widgets/icon.dart')->11797\n",
      "Library('package:flutter/src/widgets/icon_data.dart')->11717\n",
      "Library('package:flutter/src/widgets/icon_theme.dart')->11767\n",
      "Library('package:flutter/src/widgets/icon_theme_data.dart')->11790\n",
      "Library('package:flutter/src/widgets/image.dart')->11831\n",
      "Library('package:flutter/src/widgets/implicit_animations.dart')->11675\n",
      "Library('package:flutter/src/widgets/inherited_notifier.dart')->11687\n",
      "Library('package:flutter/src/widgets/layout_builder.dart')->11705\n",
      "Library('package:flutter/src/widgets/localizations.dart')->11690\n",
      "Library('package:flutter/src/widgets/media_query.dart')->11779\n",
      "Library('package:flutter/src/widgets/modal_barrier.dart')->11688\n",
      "Library('package:flutter/src/widgets/navigation_toolbar.dart')->11766\n",
      "Library('package:flutter/src/widgets/navigator.dart')->11644\n",
      "Library('package:flutter/src/widgets/notification_listener.dart')->11686\n",
      "Library('package:flutter/src/widgets/overlay.dart')->11658\n",
      "Library('package:flutter/src/widgets/page_storage.dart')->11709\n",
      "Library('package:flutter/src/widgets/pages.dart')->11650\n",
      "Library('package:flutter/src/widgets/performance_overlay.dart')->11781\n",
      "Library('package:flutter/src/widgets/preferred_size.dart')->11798\n",
      "Library('package:flutter/src/widgets/primary_scroll_controller.dart')->11773\n",
      "Library('package:flutter/src/widgets/routes.dart')->11649\n",
      "Library('package:flutter/src/widgets/safe_area.dart')->11769\n",
      "Library('package:flutter/src/widgets/scroll_configuration.dart')->11793\n",
      "Library('package:flutter/src/widgets/scroll_controller.dart')->11786\n",
      "Library('package:flutter/src/widgets/scroll_metrics.dart')->11784\n",
      "Library('package:flutter/src/widgets/scroll_position.dart')->11785\n",
      "Library('package:flutter/src/widgets/semantics_debugger.dart')->11740\n",
      "Library('package:flutter/src/widgets/text.dart')->11782\n",
      "Library('package:flutter/src/widgets/ticker_provider.dart')->11647\n",
      "Library('package:flutter/src/widgets/title.dart')->11780\n",
      "Library('package:flutter/src/widgets/transitions.dart')->11651\n",
      "Library('package:flutter/src/widgets/widget_inspector.dart')->11681\n",
      "Library('package:flutter/src/widgets/widget_span.dart')->11844\n",
      "Library('package:myapp/main.dart')->11847\n",
      "Library('package:typed_data/typed_buffers.dart')->11704\n",
      "Library('package:vector_math/hash.dart')->11812\n",
      "Library('package:vector_math/vector_math_64.dart')->11813\n"
     ]
    }
   ],
   "source": [
    "for lib in sorted(s.getrefs('Library'), key=lambda x: x.x['url'].x['value']):\n",
    "    print(lib)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However if the app is obfuscated, the names will be gibberish. In this case, we need..."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deobfuscation\n",
    "\n",
    "The Dart snapshotter has support for obfuscation. It's easy to enable, and it renames identifiers (i.e. library URLs, class names, function names, field names) to random three-letter strings. This obfuscation is per string, so two functions named the same will also have the same obfuscated identifier. Also, some identifiers that are special to the VM (such as the top-level class name, `::`) are left untouched. This obfuscation is applied to everything, including dependencies and internal (i.e. Dart or Flutter) code.\n",
    "\n",
    "This brings up a need for deobfuscation. The process can be summarized as:\n",
    "\n",
    " 1. Find open-source dependencies used in the app.\n",
    " 2. Build a *reference snapshot* that contains these open-source dependencies.\n",
    " 3. Attempt to match functions in both snapshots, so we can unmask their real names.\n",
    "\n",
    "This deobfuscates most of the identifiers, helps us separate useful code from dependencies, and helps us see what the useful code is doing.  \n",
    "In my experience, the fastest way to do this is:\n",
    "\n",
    " 1. Build an empty app. This will be the reference snapshot.\n",
    " 2. Print a string table, as we did before, but excluding strings that are present in the reference snapshot.\n",
    " 3. Look at the strings, google them, find the package they're defined in.\n",
    " 4. When you have found a package, import it in the app and rebuild it.\n",
    " 5. Go to step (2); this time there'll be less strings.  \n",
    " 6. When only useful strings are left, the reference snapshot has all the dependencies. Use it to deobfuscate the names.\n",
    "\n",
    "However, Dart has a powerful **tree shaker** which will remove any dependencies we are not using. So, importing these dependencies in our empty app is not enough, we would have to call every function in their public API in order for them to be included in the reference snapshot. Because this is long and tedious, it's better to patch Dart to disable this tree shaker.\n",
    "\n",
    "TODO: continue explanation; publish nref-based deobfuscation code; add obfuscated sample"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Print library structure"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Given a certain library, we can print all classes, functions, fields and constants in it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Library('package:myapp/main.dart')->11847\n"
     ]
    }
   ],
   "source": [
    "lib = s.strings['package:myapp/main.dart'].src[1][0]\n",
    "print(lib)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
